"""
插件上下文

提供插件运行时的上下文环境和服务。
"""

import os
from typing import Any, Dict, List, Optional, Callable
from pathlib import Path
import logging

from .exceptions import PluginError


class PluginContext:
    """
    插件上下文

    为插件提供运行时环境和服务访问。
    """

    def __init__(
        self,
        base_path: str = "./plugins",
        data_path: str = "./data/plugins",
        config: Optional[Dict[str, Any]] = None,
    ):
        self.base_path = Path(base_path)
        self.data_path = Path(data_path)
        self.config = config or {}

        # 服务注册表
        self._services: Dict[str, Any] = {}

        # 事件系统
        self._event_handlers: Dict[str, List[Callable]] = {}

        # 共享数据
        self._shared_data: Dict[str, Any] = {}

        # 日志系统
        self._setup_logging()

        # 确保目录存在
        self._ensure_directories()

    def _setup_logging(self) -> None:
        """设置日志系统"""
        self.logger = logging.getLogger("plugin_context")

        # 如果没有处理器，添加默认处理器
        if not self.logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter(
                "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
            )
            handler.setFormatter(formatter)
            self.logger.addHandler(handler)
            self.logger.setLevel(logging.INFO)

    def _ensure_directories(self) -> None:
        """确保必要的目录存在"""
        self.base_path.mkdir(parents=True, exist_ok=True)
        self.data_path.mkdir(parents=True, exist_ok=True)

    # ========================================================================
    # 路径管理
    # ========================================================================

    def get_plugin_path(self, plugin_name: str) -> str:
        """获取插件目录路径"""
        return str(self.base_path / plugin_name)

    def get_resource_path(self, plugin_name: str, resource_name: str) -> str:
        """获取插件资源路径"""
        plugin_path = self.base_path / plugin_name
        resource_path = plugin_path / "resources" / resource_name
        return str(resource_path)

    def get_data_path(self, plugin_name: str, filename: str) -> str:
        """获取插件数据路径"""
        plugin_data_path = self.data_path / plugin_name
        plugin_data_path.mkdir(parents=True, exist_ok=True)
        return str(plugin_data_path / filename)

    def get_config_path(self, plugin_name: str) -> str:
        """获取插件配置路径"""
        return str(self.data_path / plugin_name / "config.yaml")

    def get_log_path(self, plugin_name: str) -> str:
        """获取插件日志路径"""
        log_dir = self.data_path / plugin_name / "logs"
        log_dir.mkdir(parents=True, exist_ok=True)
        return str(log_dir / f"{plugin_name}.log")

    # ========================================================================
    # 服务管理
    # ========================================================================

    def register_service(self, name: str, service: Any) -> None:
        """注册服务"""
        self._services[name] = service

    def get_service(self, name: str) -> Optional[Any]:
        """获取服务"""
        return self._services.get(name)

    def unregister_service(self, name: str) -> bool:
        """注销服务"""
        if name in self._services:
            del self._services[name]
            return True
        return False

    def list_services(self) -> List[str]:
        """列出所有服务"""
        return list(self._services.keys())

    def has_service(self, name: str) -> bool:
        """检查服务是否存在"""
        return name in self._services

    # ========================================================================
    # 事件系统
    # ========================================================================

    def subscribe(self, event_name: str, handler: Callable) -> None:
        """订阅事件"""
        if event_name not in self._event_handlers:
            self._event_handlers[event_name] = []
        self._event_handlers[event_name].append(handler)

    def unsubscribe(self, event_name: str, handler: Callable) -> bool:
        """取消订阅事件"""
        if event_name in self._event_handlers:
            try:
                self._event_handlers[event_name].remove(handler)
                return True
            except ValueError:
                pass
        return False

    def emit(self, event_name: str, *args, **kwargs) -> None:
        """发布事件"""
        if event_name in self._event_handlers:
            for handler in self._event_handlers[event_name]:
                try:
                    handler(*args, **kwargs)
                except Exception as e:
                    self.logger.error(f"事件处理器执行失败: {e}")

    def list_events(self) -> List[str]:
        """列出所有事件"""
        return list(self._event_handlers.keys())

    # ========================================================================
    # 共享数据
    # ========================================================================

    def set_shared_data(self, key: str, value: Any) -> None:
        """设置共享数据"""
        self._shared_data[key] = value

    def get_shared_data(self, key: str, default: Any = None) -> Any:
        """获取共享数据"""
        return self._shared_data.get(key, default)

    def remove_shared_data(self, key: str) -> bool:
        """移除共享数据"""
        if key in self._shared_data:
            del self._shared_data[key]
            return True
        return False

    def list_shared_data(self) -> List[str]:
        """列出所有共享数据键"""
        return list(self._shared_data.keys())

    def clear_shared_data(self) -> None:
        """清空共享数据"""
        self._shared_data.clear()

    # ========================================================================
    # 配置管理
    # ========================================================================

    def get_global_config(self, key: str, default: Any = None) -> Any:
        """获取全局配置"""
        return self.config.get(key, default)

    def set_global_config(self, key: str, value: Any) -> None:
        """设置全局配置"""
        self.config[key] = value

    def load_plugin_config(self, plugin_name: str) -> Dict[str, Any]:
        """加载插件配置"""
        config_path = self.get_config_path(plugin_name)

        if not os.path.exists(config_path):
            return {}

        try:
            import yaml

            with open(config_path, "r", encoding="utf-8") as f:
                return yaml.safe_load(f) or {}
        except Exception as e:
            self.logger.error(f"加载插件配置失败 {plugin_name}: {e}")
            return {}

    def save_plugin_config(self, plugin_name: str, config: Dict[str, Any]) -> bool:
        """保存插件配置"""
        config_path = self.get_config_path(plugin_name)

        try:
            import yaml

            os.makedirs(os.path.dirname(config_path), exist_ok=True)
            with open(config_path, "w", encoding="utf-8") as f:
                yaml.dump(config, f, default_flow_style=False, allow_unicode=True)
            return True
        except Exception as e:
            self.logger.error(f"保存插件配置失败 {plugin_name}: {e}")
            return False

    # ========================================================================
    # 日志管理
    # ========================================================================

    def get_logger(self, plugin_name: str) -> logging.Logger:
        """获取插件专用日志器"""
        logger = logging.getLogger(f"plugin.{plugin_name}")

        # 如果没有处理器，添加文件处理器
        if not logger.handlers:
            log_path = self.get_log_path(plugin_name)
            handler = logging.FileHandler(log_path, encoding="utf-8")
            formatter = logging.Formatter(
                "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
            )
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            logger.setLevel(logging.INFO)

        return logger

    # ========================================================================
    # 权限管理
    # ========================================================================

    def check_permission(self, plugin_name: str, permission: str) -> bool:
        """检查插件权限"""
        # 简化实现，实际应该有更复杂的权限系统
        plugin_permissions = self.get_global_config(
            f"plugins.{plugin_name}.permissions", []
        )
        return permission in plugin_permissions or "all" in plugin_permissions

    def grant_permission(self, plugin_name: str, permission: str) -> None:
        """授予插件权限"""
        key = f"plugins.{plugin_name}.permissions"
        permissions = self.get_global_config(key, [])
        if permission not in permissions:
            permissions.append(permission)
            self.set_global_config(key, permissions)

    def revoke_permission(self, plugin_name: str, permission: str) -> None:
        """撤销插件权限"""
        key = f"plugins.{plugin_name}.permissions"
        permissions = self.get_global_config(key, [])
        if permission in permissions:
            permissions.remove(permission)
            self.set_global_config(key, permissions)

    # ========================================================================
    # 工具方法
    # ========================================================================

    def create_temp_file(self, plugin_name: str, suffix: str = ".tmp") -> str:
        """创建临时文件"""
        import tempfile

        temp_dir = self.data_path / plugin_name / "temp"
        temp_dir.mkdir(parents=True, exist_ok=True)

        fd, path = tempfile.mkstemp(suffix=suffix, dir=str(temp_dir))
        os.close(fd)
        return path

    def cleanup_temp_files(self, plugin_name: str) -> None:
        """清理临时文件"""
        temp_dir = self.data_path / plugin_name / "temp"
        if temp_dir.exists():
            import shutil

            shutil.rmtree(str(temp_dir))
            temp_dir.mkdir(parents=True, exist_ok=True)

    def get_system_info(self) -> Dict[str, Any]:
        """获取系统信息"""
        import platform
        import sys

        return {
            "platform": platform.platform(),
            "python_version": sys.version,
            "architecture": platform.architecture(),
            "processor": platform.processor(),
            "memory": self._get_memory_info(),
        }

    def _get_memory_info(self) -> Dict[str, Any]:
        """获取内存信息"""
        try:
            import psutil

            memory = psutil.virtual_memory()
            return {
                "total": memory.total,
                "available": memory.available,
                "percent": memory.percent,
            }
        except ImportError:
            return {"error": "psutil not available"}

    # ========================================================================
    # 上下文管理
    # ========================================================================

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cleanup()

    def cleanup(self) -> None:
        """清理上下文"""
        self._services.clear()
        self._event_handlers.clear()
